package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.MachineOpLog;
import com.tbit.main.constant.MachineAbnormalConstant;
import com.tbit.main.constant.MachineFunctionConstant;
import com.tbit.main.constant.enums.MachineFunctionMode;
import com.tbit.main.controller.interceptor.LoginUserContextHolder;
import com.tbit.main.dao.core.MachineFunctionDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.AccountUser;
import com.tbit.main.pojo.Camera;
import com.tbit.main.pojo.Machine;
import com.tbit.main.pojo.MachineFunction;
import com.tbit.main.service.*;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.tbit.main.constant.MachineFunctionConstant.*;

/**
 * @author LMY
 * @create 2022-02-25 14:00
 */
@Service("machineFunctionService")
public class MachineFunctionServiceImpl implements MachineFunctionService {

    @Autowired
    private DataService dataService;
    @Autowired
    private MachineFunctionDao machineFunctionDao;
    @Autowired
    private CameraService cameraService;
    @Autowired
    private HelmetBoundService helmetBoundService;
    @Autowired
    private HelmetAbnormalService helmetAbnormalService;
    @Autowired
    private MachineAbnormalService machineAbnormalService;
    @Autowired
    private MachineOpLogService machineOpLogService;

    @Override
    public boolean checkIsSendControl(Integer machineId) {
        MachineFunction function =getMachineIdType(machineId, MachineFunctionConstant.MACHINE_TYPE_CAR);
        MachineFunction machineFunction =getMachineIdType(machineId, MachineFunctionConstant.MACHINE_TYPE_MTS);
        if(machineFunction!=null){
            return false;
        }
        if(function==null){
            return false;
        }
        return true;
    }

    @Override
    public MachineFunction getMachineIdType(Integer machineId, Integer type) {
        Map<String, Object> map = new HashMap<>();
        map.put("machineId", machineId);
        map.put("type", type);
        return machineFunctionDao.getMachineIdType(map);
    }

    @Override
    public MachineFunction getMachineIdHelmet(Integer machineId) {
        return machineFunctionDao.getMachineIdHelmet(machineId);
    }

    @Override
    public List<MachineFunction> getMachineIdsType(List<Integer> machineIds, Integer type) {
        Map<String, Object> map = new HashMap<>();
        map.put("machineIds", StringUtil.getListString(machineIds));
        map.put("type", type);
        return machineFunctionDao.getMachineIdsType(map);
    }

    @Override
    public List<Integer> getType(List<Integer> type) {
        return machineFunctionDao.getType(StringUtil.getListString(type));
    }

    @Override
    public void add(String machineNO, List<Integer> functionTypes, Integer functionValue,Integer photoReturnMode) {

        MachineFunction machineFunction = getMachineIdHelmet(dataService.getMachineId(machineNO));

        if (machineFunction != null && CollUtil.isNotEmpty(functionTypes)) {
            if (!functionTypes.contains(machineFunction.getFunctionType())) {
                helmetBoundService.delId(dataService.getMachineId(machineNO));
                helmetAbnormalService.delId(dataService.getMachineId(machineNO));
                machineAbnormalService.del(dataService.getMachineId(machineNO), MachineAbnormalConstant.MACHINE_ABNORMAL__HELMET);
            }
        }

        delId(machineNO);

        if (CollUtil.isNotEmpty(functionTypes)) {

            if (functionTypes.stream().noneMatch(m -> m.equals(9))) {
                cameraService.delete(machineNO);
            }

            if (functionTypes.contains(MACHINE_TYPE_HELMAT) && functionTypes.contains(MACHINE_TYPE_ZNTKS) && functionTypes.contains(MACHINE_TYPE_LYTKS)) {
                throw new BaseException("machineFunction.hemet.notone");
            }

            if (functionTypes.contains(PHOTO_RETURN_CAR) && Objects.isNull(photoReturnMode)) {
                throw new BaseException("请选择拍照还车模型");
            }

            List<Map<String, Object>> mapList = new LinkedList<>();
            List<MachineOpLog> logList = new ArrayList<>();
            Machine machine = dataService.getMachine(dataService.getMachineId(machineNO));
            AccountUser loginUser = LoginUserContextHolder.getLoginUser();

            for (Integer functionType : functionTypes) {
                Map<String, Object> map = new HashMap<>();
                map.put("machineId", dataService.getMachineId(machineNO));
                map.put("functionType", functionType);
                String functionName;
                switch (functionType) {
                    case MACHINE_TYPE_HELMAT:
                        functionName = MACHINE_TYPE_HELMAT_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_VERTICAL:
                        functionName = MACHINE_TYPE_VERTICAL_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_HIGH:
                        functionName = MACHINE_TYPE_HIGH_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_JC:
                        functionName = MACHINE_TYPE_JC_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_BLE:
                        functionName = MACHINE_TYPE_BLE_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_RFID:
                        functionName = MACHINE_TYPE_RFID_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_WEBCAM:
                        functionName = MACHINE_TYPE_WEBCAM_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_YBP:
                        functionName = MACHINE_TYPE_YBP_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case PHOTO_RETURN_CAR:
                        functionName = PHOTO_RETURN_CAR_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, "模型：" + Arrays.stream(MachineFunctionMode.values())
                            .filter(e -> e.getModeCode().equals(photoReturnMode))
                            .map(MachineFunctionMode::getModeName)
                            .findFirst()
                            .orElse("未知模型")));
                        break;
                    case MACHINE_TYPE_WMQX:
                        functionName = MACHINE_TYPE_WMQX_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));

                        Camera cameraDB = cameraService.getMachineNO(machineNO);
                        if (cameraDB == null) {
                            Camera camera = new Camera();
                            camera.setMachineNO(machineNO);
                            camera.setAccountId(dataService.getAccountId(machineNO));
                            camera.setPhotographTime(DateTimeUtil.getNowTime());
                            cameraService.insert(camera);
                        }

                        break;
                    case MACHINE_TYPE_ZNTKS:
                        functionName = MACHINE_TYPE_ZNTKS_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_CAR:
                        functionName = MACHINE_TYPE_CAR_NAME;
                        break;
                    case MACHINE_TYPE_MTS:
                        functionName = MACHINE_TYPE_MTS_NAME;
                        break;
                    case MACHINE_TYPE_CDZ:
                        functionName = MACHINE_TYPE_CDZ_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_NOPOINT:
                        functionName = MACHINE_TYPE_NOPOINT_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_LYTKS:
                        functionName = MACHINE_TYPE_LYTKS_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_LYTKS_ONE:
                        functionName = MACHINE_TYPE_LYTKS_ONE_NAME;
                        break;
                    case MACHINE_TYPE_LYTKS_T:
                        functionName = MACHINE_TYPE_LYTKS_T_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    case MACHINE_TYPE_RGPS:
                        functionName = MACHINE_TYPE_RGPS_NAME;
                        logList.add(buildOpLog(functionType, "添加", machine, loginUser, null));
                        break;
                    default:
                        throw new BaseException("type.not.exit");
                }
                map.put("functionName", functionName);
                map.put("functionValue", functionValue);
                map.put("updateTime", DateTimeUtil.getNowTime());
                map.put("functionMode", photoReturnMode);
                mapList.add(map);
            }
            machineFunctionDao.addBatch(mapList);
            machineOpLogService.insertBatch(logList.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList())
            );

        } else {
            cameraService.delete(machineNO);
            helmetBoundService.delId(dataService.getMachineId(machineNO));
            helmetAbnormalService.delId(dataService.getMachineId(machineNO));
            machineAbnormalService.del(dataService.getMachineId(machineNO), MachineAbnormalConstant.MACHINE_ABNORMAL__HELMET);
        }


    }

    private MachineOpLog buildOpLog(Integer functionType, String opType, Machine machine, AccountUser loginUser, String detail) {
        String functionName = getFunctionName(functionType);
        if (functionName == null) {
            return null;
        }

        return MachineOpLog.builder()
                .accountId(machine.getAccountId())
                .machineId(machine.getMachineId())
                .machineNO(machine.getMachineNO())
                .userCode(machine.getUserCode())
                .operation("功能配置-" + getFunctionName(functionType))
                .opType(opType)
                .opUser(loginUser.getName())
                .opUserPhone(loginUser.getPhone())
                .opPlatform(OperationPlatform.MAINTAIN.code)
                .opTime(LocalDateTime.now())
                .result(true)
                .build();
    }

    private String getFunctionName(Integer type) {
        switch (type) {
            case MACHINE_TYPE_HELMAT:
                return "头盔锁";
            case MACHINE_TYPE_VERTICAL:
                return "垂直停车";
            case MACHINE_TYPE_HIGH:
                return "高精度";
            case MACHINE_TYPE_JC:
                return "脚撑";
            case MACHINE_TYPE_BLE:
                return "道钉";
            case MACHINE_TYPE_RFID:
                return "RFID";
            case MACHINE_TYPE_WEBCAM:
                return "摄像头";
            case MACHINE_TYPE_YBP:
                return "仪表盘";
            case PHOTO_RETURN_CAR:
                return "拍照还车";
            case MACHINE_TYPE_WMQX:
                return "文明骑行";
            case MACHINE_TYPE_ZNTKS:
                return "智能头盔锁";
            case MACHINE_TYPE_CDZ:
                return "充电桩";
            case MACHINE_TYPE_NOPOINT:
                return "无定位车辆";
            case MACHINE_TYPE_LYTKS:
                return "蓝牙头盔锁";
            case MACHINE_TYPE_LYTKS_T:
                return "绿T标线摄像头";
            default:
                return null;
        }
    }

    @Override
    public void del(String machineNO, Integer functionType) {
        Map<String, Object> map = new HashMap<>();
        map.put("machineId", dataService.getMachineId(machineNO));
        map.put("functionType", functionType);
        machineFunctionDao.del(map);

        AccountUser loginUser = LoginUserContextHolder.getLoginUser();
        Machine machine = dataService.getMachine(dataService.getMachineId(machineNO));
        machineOpLogService.insertSingle(buildOpLog(functionType, "删除", machine, loginUser, null));
    }

    @Override
    public void delId(String machineNO) {
        machineFunctionDao.delId(dataService.getMachineId(machineNO));
    }

    @Override
    public void closeMachineId(Integer machineId, List<Integer> functionTypes) {
        Map<String, Object> map = new HashMap<>();
        map.put("machineId", machineId);
        if (CollUtil.isNotEmpty(functionTypes)) {
            map.put("functionTypes", StringUtil.getListString(functionTypes));
        }
        machineFunctionDao.closeMachineId(map);
    }


    @Override
    public List<MachineFunction> getMachineId(Integer machineId) {
        return machineFunctionDao.getMachineId(machineId);
    }

    /**
     * 批量新增功能配置
     * @param functions 功能参数
     */
    @Override
    public void batchAdd(List<MachineFunction> functions) {
        machineFunctionDao.bachAddFunction(functions);
    }


    /**
     * 摄像头配置
     * @param cameraList 摄像头配置
     */
    @Override
    public void addCameraBatch(List<Camera> cameraList) {
        machineFunctionDao.addCameraBatch(cameraList);
    }
}
